package com.dsg.controller.apply;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dsg.common.dto.OldCardDto;
import com.dsg.common.util.BeanKit;
import com.dsg.entity.apply.DsgApplyCheck;
import com.dsg.entity.dto.*;
import com.dsg.entity.oil.DsgOilLimit;
import com.dsg.entity.system.DsgSysFile;
import com.dsg.service.apply.IDsgApplyCheckService;
import com.dsg.common.constants.MessageConstants;
import com.dsg.common.dto.AjaxResult;
import com.dsg.common.security.SystemAuthorizingUser;
import com.dsg.common.util.SingletonLoginUtils;
import com.dsg.common.util.UUIDGenerator;
import com.dsg.common.util.toolbox.CollectionUtil;
import com.dsg.common.util.toolbox.DateUtil;
import com.dsg.common.util.toolbox.StringUtil;
import com.dsg.controller.base.BaseController;
import com.dsg.entity.apply.*;
import com.dsg.entity.approve.DsgApproveCase;
import com.dsg.entity.coupon.DsgCouponSend;
import com.dsg.service.apply.*;
import com.dsg.service.approve.IDsgApproveCaseService;
import com.dsg.service.coupon.IDsgCouponSendService;
import com.dsg.service.system.IDsgSysFileService;
import com.dsg.util.Constant;
import com.dsg.util.FileUtil;
import com.dsg.util.SnowflakeKeyWorker;
import com.dsg.workflow.WorkflowEngine;
import com.dsg.workflow.WorkflowService3;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务申请单 前端控制器
 * </p>
 *
 * @author system
 * @since 2020-07-10
 */
@RestController
@RequestMapping("/apply/dsgApplyBill")
@Api(description = "业务申请单")
@Slf4j
public class DsgApplyBillController extends BaseController {

    @Autowired
    private IDsgApplyContactService contactService;
    @Autowired
    private IDsgApplyDiscountService discountService;
    @Autowired
    private IDsgApplyPayService payService;
    @Autowired
    private IDsgApplyCardService cardService;
    @Autowired
    private IDsgApplyCarService carService;
    @Autowired
    private IDsgApplyCusService cusService;
    @Autowired
    private IDsgApplyQuestionService questionService;
    @Autowired
    private IDsgApplyBillService service;
    @Autowired
    IDsgCouponSendService couponSendService;
    @Autowired
    private IDsgApplyComService comService;
    @Autowired
    private IDsgApproveCaseService caseService;
    @Autowired
    IDsgApplyCheckService checkService;
    @Autowired
    IDsgApplyStatusService statusService;
    @Autowired
    IDsgApplyResultService resultService;
    @Autowired
    IDsgSysFileService fileService;
    @Autowired
    WorkflowEngine engine;
    @Autowired
    WorkflowService3 w3;

    @Transactional(rollbackFor = Exception.class)
    @PostMapping(value = "/{id}/salesCancel")
    @ApiOperation("Sales入機作廢")
    public AjaxResult salesCancel(@PathVariable String id) throws Exception {
        DsgApplyBill applyBill = service.getById(id);
        if (applyBill.getAppStatus() != DsgApplyBill.APP_STATUS_6) {
            return setErrorJson("只能作廢草稿");
        }
        applyBill.setAppStatus(DsgApplyBill.APP_STATUS_8);
        service.updateById(applyBill);
        return json(MessageConstants.SSO_STATUS_SUCCESS, null);
    }

    @Transactional(rollbackFor = Exception.class)
    @PostMapping(value = "/{id}/salesSubmit")
    @ApiOperation("Sales入機提交")
    public AjaxResult salesSubmit(@PathVariable String id) throws Exception {
        DsgApplyBill applyBill = service.getById(id);
        if (applyBill.getAppStatus() != DsgApplyBill.APP_STATUS_6) {
            return setErrorJson("只能提交草稿");
        }
        applyBill.setAppStatus(DsgApplyBill.APP_STATUS_DRAFT);
        service.updateById(applyBill);
        return json(MessageConstants.SSO_STATUS_SUCCESS, null);
    }

    @Transactional(rollbackFor = Exception.class)
    @PostMapping(value = "/salesBatchSubmit")
    @ApiOperation("Sales入機批量提交")
    public AjaxResult salesBatchSubmit(String ids) throws Exception {
        List<String> idList = Arrays.asList(ids.split(","));
        for (String id : idList) {
            DsgApplyBill applyBill = service.getById(id);
            if (applyBill.getAppStatus() != DsgApplyBill.APP_STATUS_6) {
                return setErrorJson("只能提交草稿");
            }
            applyBill.setAppStatus(DsgApplyBill.APP_STATUS_DRAFT);
            service.updateById(applyBill);
        }
        return json(MessageConstants.SSO_STATUS_SUCCESS, null);
    }

    @Transactional(rollbackFor = Exception.class)
    @PostMapping(value = "/{id}/submit")
    @ApiOperation("提交")
    public AjaxResult submit(@PathVariable String id) throws Exception {
        DsgApplyBill applyBill = service.getById(id);
        if (applyBill.getAppStatus() != DsgApplyBill.APP_STATUS_DRAFT) {
            return setErrorJson("只能提交草稿");
        }

        DsgApproveCase applyCase = caseService.getApplyCase(applyBill.getAppNo());
        if (applyCase == null) {
            throw new Exception("無開始CASE，請先保存付款資料");
        }
        engine.fileComplete(applyCase);
        log.info("workflow forward: {}", applyCase.getTaskId());
        engine.forward(applyCase);

        applyBill.setAppStatus(DsgApplyBill.APP_STATUS_1);
        service.updateById(applyBill);
        return json(MessageConstants.SSO_STATUS_SUCCESS, null);
    }

    @Transactional(rollbackFor = Exception.class)
    @PostMapping(value = "/{id}/csWaitingSubmit")
    @ApiOperation("提交")
    public AjaxResult csWaitingSubmit(@PathVariable String id) throws Exception {
        DsgApplyBill applyBill = service.getById(id);
        DsgApproveCase applyCase = caseService.getCase(WorkflowService3.NODE_CS_WAITING_LIST, applyBill.getAppNo());
        if (applyCase == null) {
            throw new Exception("无CS WAITING LIST CASE");
        }
        engine.fileComplete(applyCase);
        log.info("workflow forward: {}", applyCase.getTaskId());
        engine.forward(applyCase);

        applyBill.setAppStatus(DsgApplyBill.APP_STATUS_1);
        service.updateById(applyBill);
        return json(MessageConstants.SSO_STATUS_SUCCESS, null);
    }

    @Transactional(rollbackFor = Exception.class)
    @PostMapping(value = "/batchSubmit")
    @ApiOperation("提交")
    public AjaxResult batchSubmit(@ApiParam(value = "id以，号分隔", name = "idList", required = true) @RequestParam String idList) throws Exception {
        List<String> ids = Arrays.asList(idList.split(","));
        List<DsgApplyBill> bills = service.listByIds(ids);
        String appNos = "";
        for (DsgApplyBill applyBill : bills) {
            if (applyBill.getAppStatus() != DsgApplyBill.APP_STATUS_DRAFT) {
                return setErrorJson("只能提交草稿");
            }

            DsgApproveCase applyCase = caseService.getApplyCase(applyBill.getAppNo());
            engine.fileComplete(applyCase);
            log.info("workflow forward: {}", applyCase.getTaskId());
            engine.forward(applyCase);
            applyBill.setAppStatus(DsgApplyBill.APP_STATUS_1);
        }
        service.updateBatchById(bills);

        if (StringUtil.isNotEmpty(appNos)) {
            return setErrorJson(String.format("申請單%s因文件未齊全，未能提交", appNos));
        } else {
            return json(MessageConstants.SSO_STATUS_SUCCESS, null);
        }
    }

    @GetMapping(value = "/list")
    @ApiOperation("查询列表（分页）")
    public AjaxResult list(DsgApplyBill applyBill) {
        if (applyBill.getAppType() != DsgApplyBill.APP_TYPE_1 &&
                applyBill.getAppType() != DsgApplyBill.APP_TYPE_22) {
            applyBill.setAppType(null);
        }
        Page page = getPage();
        applyBill.setEntCode(getEntCode());
        applyBill.setCreater(SingletonLoginUtils.getSystemUserId());
        page = service.selectByList(page, applyBill);
        AjaxResult ajaxResult = json(MessageConstants.SSO_STATUS_SUCCESS, page.getRecords(), (int) page.getTotal());
        return ajaxResult;
    }

    @GetMapping(value = "/salesWaitingList")
    @ApiOperation("Sales waiting list 查询列表（分页）")
    public AjaxResult selectSalesWaitingList(DsgApplyBill applyBill) {
        Page page = getPage();
        applyBill.setEntCode(getEntCode());
        applyBill.setCreater(getUserId());
        page = service.selectSalesWaitingList(page, applyBill);
        AjaxResult ajaxResult = json(MessageConstants.SSO_STATUS_SUCCESS, page.getRecords(), (int) page.getTotal());
        return ajaxResult;
    }

    @GetMapping(value = "/salesManagerList")
    @ApiOperation("Sales Manager waiting list 查询列表（分页）")
    public AjaxResult salesManagerList(DsgApplyBill applyBill) {
        Page page = getPage();
        applyBill.setEntCode(getEntCode());
        page = service.selectSalesManagerList(page, applyBill);
        AjaxResult ajaxResult = json(MessageConstants.SSO_STATUS_SUCCESS, page.getRecords(), (int) page.getTotal());
        return ajaxResult;
    }

    @GetMapping(value = "/salesList")
    @ApiOperation("Sales waiting list 查询列表（分页）")
    public AjaxResult salesList(DsgApplyBill applyBill) {
        Page page = getPage();
        applyBill.setEntCode(getEntCode());
        page = service.selectByList(page, applyBill);
        AjaxResult ajaxResult = json(MessageConstants.SSO_STATUS_SUCCESS, page.getRecords(), (int) page.getTotal());
        return ajaxResult;
    }

    @GetMapping(value = "/csWaitingList")
    @ApiOperation("CS waiting list 查询列表（分页）")
    public AjaxResult csWaitingList(DsgApplyBill applyBill) {
        Page page = getPage();
        applyBill.setEntCode(getEntCode());
        page = service.csWaitingList(page, applyBill);
        AjaxResult ajaxResult = json(MessageConstants.SSO_STATUS_SUCCESS, page.getRecords(), (int) page.getTotal());
        return ajaxResult;
    }

    /**
     * 查询单条数据
     *
     * @param id
     * @return
     */
    @GetMapping(value = "/{id}/view")
    @ApiOperation("查询单条数据")
    public AjaxResult view(@PathVariable String id) {
        DsgApplyBill applyBill = service.getById(id);
        return json(MessageConstants.SSO_STATUS_SUCCESS, applyBill);
    }

    @PostMapping(value = "/{id}/cancel")
    @ApiOperation("作废单条数据")
    public AjaxResult cancel(@PathVariable String id) {
        DsgApplyBill applyBill = service.getById(id);
        applyBill.setAppStatus(DsgApplyBill.APP_STATUS_2);
        service.saveOrUpdate(applyBill);
        return json(MessageConstants.SSO_STATUS_SUCCESS, applyBill);
    }

    /**
     * 新增
     *
     * @param applyBill
     * @return
     */
    @PostMapping(value = "/add")
    @ApiOperation("新增")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult add(@RequestBody DsgApplyBill applyBill) throws Exception {
        if (StringUtil.isEmpty(applyBill.getMainNo()) &&
                StringUtil.isEmpty(applyBill.getAppNo()) &&
                StringUtil.isEmpty(applyBill.getCusId())) {
            String appNo = DateUtil.format(new Date(), "yyyyMMddHHmmss");
            applyBill.setAppNo(appNo);
            applyBill.setMainNo(appNo);
        } else if (StringUtil.isNotEmpty(applyBill.getMainNo()) &&
                StringUtil.isNotEmpty(applyBill.getAppNo()) &&
                StringUtil.isNotEmpty(applyBill.getCusId())) {
            //此情況為已經存在的客戶再次做新申請
        } else {
            return fail("mainNo和appNo要同時為空或不為空");
        }

        applyBill.setOid(UUIDGenerator.getUUID());
        applyBill.setApplyTime(new Date());
        SystemAuthorizingUser sysUser = SingletonLoginUtils.getSystemUser();
        applyBill.setSalerNo(sysUser.getUserName());
        applyBill.setSaleTeam(sysUser.getOrgCode());
        if (DsgApplyBill.APP_TYPE_1 == applyBill.getAppType() || DsgApplyBill.APP_TYPE_22 == applyBill.getAppType()) {
            applyBill.setAppStatus(DsgApplyBill.APP_STATUS_6);
        }
        if (DsgApplyBill.KEEP_TYPE_CASH == applyBill.getKeepType())
            applyBill.setPayType(Constant.PAY_TYPE_ATP);

        service.save(applyBill);
        log.info("workflow begin: {}", applyBill.getMainNo());
        if (StringUtil.isNotEmpty(applyBill.getPayType()) || DsgApplyBill.KEEP_TYPE_CASH == applyBill.getKeepType())
            engine.begin(applyBill);
        return json(MessageConstants.SSO_STATUS_SUCCESS, applyBill);
    }

    /**
     * @param applyBill
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @PutMapping(value = "/saveOrUpdate")
    @ApiOperation("新增或更新")
    public AjaxResult saveOrUpdate(@RequestBody DsgApplyBill applyBill) throws Exception {
//        if (StringUtil.isEmpty(applyBill.getOid())) {
//            applyBill.setApplyTime(new Date());
//            applyBill.setOid(UUIDGenerator.getUUID());
//            String appNo = DateUtil.format(new Date(), "yyyyMMddHHmmss");
//            applyBill.setAppNo(appNo);
//            applyBill.setMainNo(appNo);
//            SystemAuthorizingUser sysUser = SingletonLoginUtils.getSystemUser();
//            applyBill.setSalerNo(sysUser.getUserName());
//            applyBill.setSaleTeam(sysUser.getOrgCode());
//        }
        if (applyBill.getAppType() == DsgApplyBill.APP_TYPE_7 ||
                applyBill.getAppType() == DsgApplyBill.APP_TYPE_15 ||
                applyBill.getAppType() == DsgApplyBill.APP_TYPE_16) {
            DsgApplyBill applyBillTemp = service.getById(applyBill.getOid());
            applyBill.setPayType(applyBillTemp.getPayType());
            if (StringUtil.isEmpty(applyBillTemp.getPayId())) {
                return fail("未選擇付款資料");
            }
        } else if (applyBill.getKeepType() == DsgApplyBill.KEEP_TYPE_CASH) {
            applyBill.setPayType(Constant.PAY_TYPE_ATP);
        }

        applyBill.setAppStatus(null);//設為null則不會更新該字段
        applyBill.setIsSave(DsgApplyBill.IS_SAVE_Y);
        service.saveOrUpdate(applyBill);

        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("MAIN_NO", applyBill.getMainNo());
        wrapper.eq("QUE_TYPE", DsgApplyQuestion.QUE_TYPE_BILL);
        questionService.remove(wrapper);
        DsgApplyQuestion question = applyBill.getQuestion();
        if (question != null) {
            if (StringUtil.isEmpty(question.getOid())) {
                question.setOid(UUIDGenerator.getUUID());
                question.setMainNo(applyBill.getMainNo());
                question.setQueType(DsgApplyQuestion.QUE_TYPE_BILL);
            }
            questionService.saveOrUpdate(question);
        }

        if (applyBill.getAppType() == DsgApplyBill.APP_TYPE_7 ||
                applyBill.getAppType() == DsgApplyBill.APP_TYPE_15 ||
                applyBill.getAppType() == DsgApplyBill.APP_TYPE_16 ||
                applyBill.getAppType() == DsgApplyBill.APP_TYPE_21 ||
                applyBill.getAppType() == DsgApplyBill.APP_TYPE_22) {
            engine.begin(applyBill);
        }

        return json(MessageConstants.SSO_STATUS_SUCCESS, applyBill);
    }

    /**
     * 批量删除
     *
     * @return
     */
    @DeleteMapping(value = "/delete")
    @ApiOperation("批量删除")
    public AjaxResult delete(@ApiParam(value = "id以，号分隔", name = "idList", required = true) @RequestParam String idList) {
        Boolean flag = service.removeByIds(Arrays.asList(idList.split(",")));
        if (flag) {
            return result(MessageConstants.SSO_STATUS_SUCCESS);
        } else {
            return result(MessageConstants.SSO_STATUS_FAIL);
        }
    }

    @GetMapping(value = "/{id}/csView")
    @ApiOperation("cs入机详细资料")
    @ApiResponses({
            @ApiResponse(response = CsApplyDetailDto.class, code = 1, message = "ok")
    })
    public AjaxResult csView(@PathVariable String id) {
        CsApplyDetailDto detailDto = getCsApplyDetailDto(id, false);
        return json(MessageConstants.SSO_STATUS_SUCCESS, detailDto);
    }

    /**
     * 對於內審失敗的，會調用兩次該接口
     * todo 何時產生開始case
     */
    @PostMapping(value = "/copyBill")
    @ApiOperation("拒絕車列表-翻生-創建新的單")
    @ApiResponses({
            @ApiResponse(response = CsApplyDetailDto.class, code = 1, message = "ok")
    })
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult copyBill(@RequestBody CopyBillDto dto) throws Exception {
        CsApplyDetailDto detailDto = getCsApplyDetailDto(dto.getBillOid(), false);
        DsgApplyBill bill = detailDto.getDsgApplyBill();

        List<DsgApplyCar> carList = detailDto.getCarList();

        List<DsgApplyCar> sameBillCarList = carList.stream().filter(e -> dto.getCarOids().contains(e.getOid())).collect(Collectors.toList());
//        翻生的时候，先做一次内审，假如
//        成功，直接翻生     失败，提示是否需要强行通过，如果通过才创建翻生单
        if (dto.getForcePass() == null || !dto.getForcePass()) {
            boolean success = carService.rebornCarAudi(bill, sameBillCarList);
            if (!success) {
                return new AjaxResult(MessageConstants.AUDIT_CHECK_FAIL);
            }
        }

        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("APP_NO", bill.getAppNo());
        List<DsgSysFile> files = fileService.list(wrapper);
        List<DsgSysFile> copyFiles = new ArrayList<>();
        List<DsgSysFile> tempFiles = files.stream().filter(e -> e.getRelId().equals(dto.getBillOid())).collect(Collectors.toList());

        BeanKit.resetCommonField(bill);
        bill.setOid(UUIDGenerator.getUUID());
        bill.setAppStatus(DsgApplyBill.APP_STATUS_DRAFT);
        String appNo = DateUtil.format(new Date(), "yyyyMMddHHmmss");
        bill.setAppNo(appNo);
        bill.setApplyTime(new Date());
        service.save(bill);

//        DsgApplyQuestion question = bill.getQuestion();
//        BeanKit.resetCommonField(question);
//        question.setOid(UUIDGenerator.getUUID());
//        questionService.save(question);

        tempFiles.forEach(e -> {
            e.setOid(UUIDGenerator.getUUID());
            e.setRelId(bill.getOid());
            e.setAppNo(bill.getAppNo());
            BeanKit.resetCommonField(e);
        });
        copyFiles.addAll(tempFiles);

        List<DsgApplyCar> copyCarList = new ArrayList<>();
        List<DsgApplyCard> copyCardList = new ArrayList<>();
        List<DsgApplyQuestion> questions = new ArrayList<>();
        List<DsgApplyDiscount> copyDiscountList = new ArrayList<>();
        List<DsgApplyStatus> statusList = new ArrayList<>();
        List<DsgCouponSend> copyCouponList = new ArrayList<>();
        for (DsgApplyCar car : sameBillCarList) {
            if (DsgApplyCar.CAR_STATUS_REBORN == car.getCarStatus()) {
                throw new Exception(String.format("車輛%s已翻生，不能重覆翻生", car.getCarNo()));
            }
            car.setCarStatus(DsgApplyCar.CAR_STATUS_REBORN);
            DsgApplyCar copyCar = new DsgApplyCar();
            BeanUtils.copyProperties(car, copyCar);
            BeanKit.resetCommonField(copyCar);
            copyCar.setOid(UUIDGenerator.getUUID());
            copyCar.setAppNo(appNo);
            copyCar.setCarStatus(DsgApplyCar.CAR_STATUS_NOT_RECORD);
            copyCarList.add(copyCar);

            List<DsgApplyCard> cardList = car.getCardList();
            for (DsgApplyCard card : cardList) {
                BeanKit.resetCommonField(card);
                card.setOid(UUIDGenerator.getUUID());
                card.setCarId(copyCar.getOid());
                card.setAppNo(appNo);

                DsgApplyStatus status = new DsgApplyStatus();
                status.setOid(UUIDGenerator.getUUID());
                status.setAppNo(appNo);
                status.setAppType(bill.getAppType());
                status.setCarNo(car.getCarNo());
                status.setAppStatus(DsgApplyBill.APP_STATUS_DRAFT);
                statusList.add(status);

                List<DsgApplyDiscount> discountList = card.getDiscountList();
                if (CollectionUtil.isNotEmpty(discountList)) {
                    for (DsgApplyDiscount discount : discountList) {
                        BeanKit.resetCommonField(discount);
                        discount.setOid(UUIDGenerator.getUUID());
                        discount.setCardId(card.getOid());
                        copyDiscountList.add(discount);
                    }
                }

                DsgCouponSend coupon = card.getCoupon();
                if (coupon != null) {
                    BeanKit.resetCommonField(coupon);
                    coupon.setOid(UUIDGenerator.getUUID());
                    coupon.setCardId(card.getOid());
                    coupon.setAppNo(appNo);
                    copyCouponList.add(coupon);
                }
            }
            copyCardList.addAll(cardList);

            tempFiles = files.stream().filter(e -> e.getRelId().equals(car.getOid())).collect(Collectors.toList());
            tempFiles.forEach(e -> {
                e.setOid(UUIDGenerator.getUUID());
                e.setRelId(copyCar.getOid());
                e.setAppNo(appNo);
            });
            copyFiles.addAll(tempFiles);

            DsgApplyQuestion carQuestion = car.getQuestion();
            BeanKit.resetCommonField(carQuestion);
            carQuestion.setOid(UUIDGenerator.getUUID());
            carQuestion.setCarId(copyCar.getOid());
            questions.add(carQuestion);
        }
        if (CollectionUtil.isNotEmpty(copyCouponList))
            couponSendService.saveBatch(copyCouponList);
        if (CollectionUtil.isNotEmpty(copyDiscountList))
            discountService.saveBatch(copyDiscountList);
        if (CollectionUtil.isNotEmpty(statusList))
            statusService.saveBatch(statusList);
        if (CollectionUtil.isNotEmpty(copyFiles))
            fileService.saveBatch(copyFiles);
        if (CollectionUtil.isNotEmpty(questions))
            questionService.saveBatch(questions);
        carService.updateBatchById(sameBillCarList);
        if (CollectionUtil.isNotEmpty(copyCarList))
            carService.saveBatch(copyCarList);
        if (CollectionUtil.isNotEmpty(copyCardList))
            cardService.saveBatch(copyCardList);

        return json(MessageConstants.SSO_STATUS_SUCCESS, detailDto);
    }

    /**
     * @param billOid
     * @param isCheckBill 是否對單
     * @return
     */
    private CsApplyDetailDto getCsApplyDetailDto(String billOid, boolean isCheckBill) {
        CsApplyDetailDto detailDto = new CsApplyDetailDto();
        DsgApplyBill applyBill = service.getById(billOid);
        detailDto.setDsgApplyBill(applyBill);

        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("QUE_TYPE", DsgApplyQuestion.QUE_TYPE_BILL);
        wrapper.eq("MAIN_NO", applyBill.getMainNo());
        DsgApplyQuestion billQuestion = questionService.getOne(wrapper);
        applyBill.setQuestion(billQuestion);

        String cusId = applyBill.getCusId();
        String cusNo = null;
        if (StringUtil.isNotEmpty(cusId)) {
            DsgApplyCus cus = cusService.getById(cusId);
            DsgApplyCom com;
            if (cus != null) {
                cusNo = cus.getCusNo();
                detailDto.setCus(cus);
                wrapper = new QueryWrapper();
                wrapper.eq("PID", cusId);
                List<DsgApplyContact> contactList = contactService.list(wrapper);
                cus.setContactList(contactList);
            } else {
                com = comService.getById(cusId);
                cusNo = com.getComNo();
                detailDto.setCom(com);
                wrapper = new QueryWrapper();
                wrapper.eq("PID", cusId);
                List<DsgApplyContact> contactList = contactService.list(wrapper);
                com.setContactList(contactList);
            }
        }

        wrapper = new QueryWrapper();
        wrapper.eq("APP_NO", applyBill.getAppNo());
        wrapper.eq("MAIN_NO", applyBill.getMainNo());
        List<DsgApplyCar> carList = carService.list(wrapper);
        List<DsgApplyCar> carListTemp = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(carList)) {
            for (DsgApplyCar car : carList) {
                //排除已转车牌、转油种的车
                wrapper = new QueryWrapper();
                wrapper.eq("CAR_NO", car.getCarNo());
                wrapper.eq("APP_NO", car.getAppNo());
                wrapper.eq("APP_STATUS", DsgApplyStatus.APP_STATUS_CANCEL);
                DsgApplyStatus applyStatus = statusService.getOne(wrapper, false);
                if (applyStatus == null) {
                    carListTemp.add(car);
                    fillCarRelated(car);
                }
            }
            detailDto.setCarList(carListTemp);
        }

        List<DsgApplyPay> payList = new ArrayList<>();
        if (isCheckBill || applyBill.getAppType() == DsgApplyBill.APP_TYPE_7 ||
                applyBill.getAppType() == DsgApplyBill.APP_TYPE_1) {
            wrapper = new QueryWrapper();
            wrapper.eq("MAIN_NO", applyBill.getMainNo());
            payList = payService.list(wrapper);
        } else {
            DsgApplyPay pay = payService.getById(applyBill.getPayId());
            if (pay != null) {
                payList.add(pay);
            }
        }
        detailDto.setPayList(payList);

        if (StringUtil.isNotEmpty(cusNo)) {
            wrapper = new QueryWrapper();
            wrapper.eq("CUS_NO", cusNo);
            wrapper.eq("DIS_TARGET", DsgApplyDiscount.DIS_TARGET_CUS);
            List<DsgApplyDiscount> cusDiscountList = discountService.list(wrapper);
            detailDto.setCusDiscountList(cusDiscountList);
        }
        return detailDto;
    }

    /**
     * 获取车关联的数据
     *
     * @param car
     */
    private void fillCarRelated(DsgApplyCar car) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("APP_NO", car.getAppNo());
        wrapper.eq("CAR_ID", car.getOid());
        List<DsgApplyCard> cardList = cardService.list(wrapper);

        if (CollectionUtil.isNotEmpty(cardList)) {
            for (DsgApplyCard card :
                    cardList) {
                wrapper = new QueryWrapper();
                wrapper.eq("CARD_ID", card.getOid());
                wrapper.eq("DIS_TARGET", DsgApplyDiscount.DIS_TARGET_CARD);
                List<DsgApplyDiscount> cardDiscount = discountService.list(wrapper);
                card.setDiscountList(cardDiscount);

                wrapper = new QueryWrapper();
                wrapper.eq("CARD_ID", card.getOid());
                DsgCouponSend couponSend = couponSendService.getOne(wrapper);
                card.setCoupon(couponSend);

                //用回旧卡
                OldCardDto dto = new OldCardDto();
                dto.setCardId(card.getOid());
                dto = cardService.getOldCard(dto);
                dto.setCardId(null);
                dto.setNewCardId(card.getOid());
                dto = cardService.getOldCard(dto);
                if (dto != null) {
                    DsgApplyStatus status = getStatus(card.getOid(), card.getAppNo());
                    if (status != null) {
                        card.setIsUseOld(status.getIsUseOld());
                    }
                }
            }
            car.setCardList(cardList);
        }

        wrapper = new QueryWrapper();
        wrapper.eq("CAR_ID", car.getOid());
        DsgApplyQuestion question = questionService.getOne(wrapper);
        car.setQuestion(question);
    }

    @GetMapping(value = "/selectUncheckedBill")
    @ApiOperation("查询未對單列表")
    public AjaxResult selectUncheckedBill(DsgApplyBill applyBill) {
        Page page = getPage();
        applyBill.setEntCode(getEntCode());
        page = service.selectUncheckedBill(page, applyBill, false);
        AjaxResult ajaxResult = json(MessageConstants.SSO_STATUS_SUCCESS, page.getRecords(), (int) page.getTotal());
        return ajaxResult;
    }

    @GetMapping(value = "/selectCheckedBill")
    @ApiOperation("查询已對單列表")
    public AjaxResult selectCheckedBill(DsgApplyBill applyBill) {
        Page page = getPage();
        applyBill.setEntCode(getEntCode());
        page = service.selectUncheckedBill(page, applyBill, true);
        AjaxResult ajaxResult = json(MessageConstants.SSO_STATUS_SUCCESS, page.getRecords(), (int) page.getTotal());
        return ajaxResult;
    }

    @GetMapping(value = "/{id}/checkBillView")
    @ApiOperation("對單详细资料")
    public AjaxResult checkBillView(@PathVariable String id) {
        CheckBillDetailDto detailDto = new CheckBillDetailDto();
        CsApplyDetailDto detail = getCsApplyDetailDto(id, true);
        BeanUtils.copyProperties(detail, detailDto);

        DsgApplyBill applyBill = service.getById(id);
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("APP_NO", applyBill.getAppNo());
        List<DsgApplyCheck> checkList = checkService.list(wrapper);
        detailDto.setCheckList(checkList);

//        detailDto.setFileList(fileService.listByBill(applyBill.getAppNo()));

        //對單右侧的信息
        wrapper = new QueryWrapper();
        wrapper.eq("MAIN_NO", applyBill.getMainNo());
        wrapper.in("APP_TYPE", DsgApplyBill.APP_TYPE_17, DsgApplyBill.APP_TYPE_18, DsgApplyBill.APP_TYPE_19);
        wrapper.ne("APP_NO", applyBill.getAppNo());
        DsgApplyBill newBill = service.getOne(wrapper);
        if (newBill != null) {
            RightSideDto rightSideDto = new RightSideDto();
            detailDto.setRightSideDto(rightSideDto);
            rightSideDto.setBill(newBill);
            wrapper = new QueryWrapper();
            wrapper.eq("APP_NO", newBill.getAppNo());
            List<DsgApplyCar> carList = carService.list(wrapper);
            carList.forEach(e -> fillCarRelated(e));

            List<DsgSysFile> fileList = fileService.list(wrapper);
            rightSideDto.setFileList(fileList);
        }

        return json(MessageConstants.SSO_STATUS_SUCCESS, detailDto);
    }

    @PostMapping(value = "/changeCar")
    @ApiOperation("對單轉車牌、轉油種")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult changeCar(String oldCarOid, String newCarNo, int appType, String newBillOid, String oldBillOid) throws Exception {
        DsgApplyCar car = carService.getById(oldCarOid);

        if (car.getCarStatus().equals(DsgApplyCar.CAR_STATUS_CANCEL)) {
            return setErrorJson("該車已取消");
        }

        if (appType != DsgApplyBill.APP_TYPE_17 && appType != DsgApplyBill.APP_TYPE_18 && appType != DsgApplyBill.APP_TYPE_26) {
            return setErrorJson("只能轉油種和轉車牌");
        }

        if ((appType == DsgApplyBill.APP_TYPE_17 || appType == DsgApplyBill.APP_TYPE_26) && newCarNo.equals(car.getCarNo())) {
            return setErrorJson("新車牌與舊車牌一樣");
        }

        fillCarRelated(car);
        //點轉車牌，轉油種之後，這台車的記錄要變成取消，並標記為CS對單轉車牌/CS對單轉油種 取消
        car.setCarStatus(DsgApplyCar.CAR_STATUS_CANCEL);
        carService.updateById(car);

        DsgApplyBill newBill;
        if (StringUtil.isEmpty(newBillOid)) {//新的单还没有生成
            newBill = service.getById(oldBillOid);

            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("MAIN_NO", newBill.getMainNo());
            if (service.count(wrapper) > 1)
                throw new Exception("該單已經生成過新單");

            newBill.setOid(UUIDGenerator.getUUID());
            String appNo = DateUtil.format(new Date(), "yyyyMMddHHmmss");
            newBill.setMainNo(car.getMainNo());
            newBill.setAppNo(appNo);
            newBill.setAppType(appType);
            newBill.setAppStatus(DsgApplyBill.APP_STATUS_DRAFT);
            newBill.setApplyTime(new Date());
            newBill.setCreater(null);
            newBill.setCreateTime(null);
            newBill.setUpdateTime(null);
            newBill.setUpdater(null);
            service.save(newBill);
            engine.begin(newBill);
        } else {
            newBill = service.getById(newBillOid);
        }

        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("CAR_NO", car.getCarNo());
        wrapper.eq("APP_NO", car.getAppNo());
        List<DsgApplyStatus> applyStatusList = statusService.list(wrapper);
        for (DsgApplyStatus applyStatus : applyStatusList) {
            applyStatus.setAppType(newBill.getAppType());
            applyStatus.setAppStatus(DsgApplyStatus.APP_STATUS_CANCEL);
        }
        statusService.updateBatchById(applyStatusList);

        //复制车附件
        List<DsgSysFile> fileList = fileService.listByBill(car.getAppNo());
        if (CollectionUtil.isNotEmpty(fileList)) {
            String carOid = car.getOid();
            //只要该车的附件
            fileList = fileList.stream().filter(e -> e.getRelId() != null && e.getRelId().equals(carOid)).collect(Collectors.toList());
        }

        if (appType == DsgApplyBill.APP_TYPE_17) {
            car.setCarNo(newCarNo);
        } else if (appType == DsgApplyBill.APP_TYPE_18) {
            if (car.getCarOilType().equals(DsgApplyCar.CAR_OIL_TYPE_DIESEL)) {
                car.setCarOilType(DsgApplyCar.CAR_OIL_TYPE_GAS);
            } else {
                car.setCarOilType(DsgApplyCar.CAR_OIL_TYPE_DIESEL);
            }
        }
        car.setOid(UUIDGenerator.getUUID());
        car.setAppNo(newBill.getAppNo());
        car.setCarStatus(DsgApplyCar.CAR_STATUS_RECORD);
        car.setCreater(null);
        car.setCreateTime(null);
        car.setUpdateTime(null);
        car.setUpdater(null);
        carService.save(car);

        if (CollectionUtil.isNotEmpty(fileList)) {
            String appNo = car.getAppNo();
            String carOid = car.getOid();
            fileList.forEach(e -> {
                e.setOid(UUIDGenerator.getUUID());
                e.setAppNo(appNo);
                e.setRelId(carOid);
                e.setCreater(null);
                e.setCreateTime(null);
                e.setUpdateTime(null);
                e.setUpdater(null);
            });
            fileService.saveBatch(fileList);
        }

        copyCarRelated(car, newBill.getAppType());

        //车内审
        boolean ret = carService.audit(newBill, car);
        ChangeCarDto dto = new ChangeCarDto();
        dto.setCar(car);
        dto.setNewBill(newBill);

        return json(MessageConstants.SSO_STATUS_SUCCESS, dto);
    }

    @GetMapping(value = "/carAuditResult")
    @ApiOperation("對單-查看內審結果")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult carAuditResult(String carOid) {
        DsgApplyCar car = carService.getById(carOid);
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("APP_NO", car.getAppNo());
        wrapper.eq("RESULT_NAME", car.getCarNo());
        DsgApplyResult result = resultService.getOne(wrapper);
        return success(result);
    }

    @PostMapping(value = "/saveFeeAndSales")
    @ApiOperation("對單保存佣金和sales code")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult saveFeeAndSales(@RequestBody SaveFeeSalesDto dto) {
        service.updateById(dto.getBill());
        carService.updateById(dto.getCar());
        return success();
    }

    /**
     * 复制与车关联的数据，插入数据库
     */
    private void copyCarRelated(DsgApplyCar car, int appType) {
        List<DsgApplyCard> cardList = car.getCardList();
        if (CollectionUtil.isNotEmpty(cardList)) {
            for (DsgApplyCard card : cardList) {
                card.setOid(UUIDGenerator.getUUID());
                card.setCarId(car.getOid());
                card.setAppNo(car.getAppNo());

                //Caltex FC不出咭，用回原咭，所以咭號不變
                if (!(DsgOilLimit.OIL_COM_CALTEX.equals(card.getOilCom()) &&
                        DsgApplyBill.APP_TYPE_4 == appType &&
                        Constant.CARD_TYPE_SC.equals(card.getCardType()))) {
                    card.setCardNo(null);
                }

                card.setCardStatus(DsgApplyCard.CARD_STATUS_APPLY);
                card.setCardInTime(null);
                card.setCardOutTime(null);
                card.setCardEndDate(null);
                BeanKit.resetCommonField(card);
                List<DsgApplyDiscount> cardDiscount = card.getDiscountList();
                if (CollectionUtil.isNotEmpty(cardDiscount)) {
                    for (DsgApplyDiscount discount : cardDiscount) {
                        discount.setOid(UUIDGenerator.getUUID());
                        discount.setCardId(card.getOid());
                        BeanKit.resetCommonField(discount);
                    }
                    discountService.saveBatch(cardDiscount);
                }

                DsgCouponSend couponSend = card.getCoupon();
                if (couponSend != null) {
                    couponSend.setOid(UUIDGenerator.getUUID());
                    couponSend.setCardId(card.getOid());
                    BeanKit.resetCommonField(couponSend);
                    couponSendService.save(couponSend);
                }

                if (appType != DsgApplyBill.APP_TYPE_4) {
                    DsgApplyStatus status = new DsgApplyStatus();
                    status.setOid(UUIDGenerator.getUUID());
                    status.setAppNo(car.getAppNo());
                    status.setCardId(card.getOid());
                    status.setAppType(appType);
                    status.setCarNo(car.getCarNo());
                    statusService.save(status);
                }
            }
            cardService.saveBatch(cardList);
        }

        DsgApplyQuestion question = car.getQuestion();
        if (question != null) {
            question.setOid(UUIDGenerator.getUUID());
            question.setCarId(car.getOid());
            BeanKit.resetCommonField(question);
            questionService.save(question);
        }
    }

    @PostMapping(value = "/saveCarNo")
    @ApiOperation("對單转车牌改车牌后保存")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult saveCarNo(List<DsgApplyCar> carList) {
        carService.saveOrUpdateBatch(carList);
        List<DsgApplyStatus> statusList = new ArrayList<>();
        for (DsgApplyCar car : carList) {
            DsgApplyStatus applyStatus = new DsgApplyStatus();
            applyStatus.setOid(UUIDGenerator.getUUID());
            applyStatus.setCarNo(car.getCarNo());
            applyStatus.setAppType(DsgApplyBill.APP_TYPE_4);
            applyStatus.setAppStatus(DsgApplyBill.APP_STATUS_DRAFT);
            statusList.add(applyStatus);
        }
        statusService.saveBatch(statusList);
        return success();
    }

    /**
     * 返出對單页面再返回时，不能取消
     *
     * @param carOid
     * @param oldCarOid
     * @return
     */
    @PostMapping(value = "/cancelChangeCar")
    @ApiOperation("取消转车牌、转油种")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult cancelChangeCar(String carOid, String oldCarOid) {
        DsgApplyCar car = carService.getById(carOid);
        carService.removeById(carOid);
        deleteCarRelated(car);

        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("APP_NO", car.getAppNo());
        List<DsgApplyCar> carList = carService.list(wrapper);
        if (CollectionUtil.isEmpty(carList)) {
            if (carService.count(wrapper) == 0) {
                service.remove(wrapper);
            }
        }

        wrapper = new QueryWrapper();
        wrapper.eq("APP_NO", car.getAppNo());
        wrapper.eq("REL_ID", car.getOid());
        fileService.remove(wrapper);

        //还原原单的car状态
        DsgApplyCar oldCar = carService.getById(oldCarOid);
        oldCar.setCarStatus(DsgApplyCar.CAR_STATUS_RECORD);
        carService.updateById(oldCar);

        wrapper = new QueryWrapper();
        wrapper.eq("APP_NO", car.getAppNo());
        DsgApplyBill bill = service.getOne(wrapper);
        wrapper.eq("CAR_NO", car.getCarNo());
        List<DsgApplyStatus> applyStatusList = statusService.list(wrapper);
        for (DsgApplyStatus applyStatus : applyStatusList) {
            applyStatus.setAppType(bill.getAppType());
            applyStatus.setAppStatus(bill.getAppStatus());
        }
        statusService.updateBatchById(applyStatusList);

        return success();
    }

    /**
     * 删除与车关联的数据
     */
    private void deleteCarRelated(DsgApplyCar car) {
        QueryWrapper wrapper = new QueryWrapper();
//        wrapper.eq("MAIN_NO", car.getMainNo());
        wrapper.eq("CAR_ID", car.getOid());
        List<DsgApplyCard> cardList = cardService.list(wrapper);
        cardService.remove(wrapper);

        wrapper = new QueryWrapper();
        wrapper.eq("CAR_NO", car.getCarNo());
        wrapper.eq("APP_NO", car.getAppNo());
        statusService.remove(wrapper);

        if (CollectionUtil.isNotEmpty(cardList)) {
            for (DsgApplyCard card :
                    cardList) {
                wrapper = new QueryWrapper();
                wrapper.eq("CARD_ID", card.getOid());
                wrapper.eq("DIS_TARGET", DsgApplyDiscount.DIS_TARGET_CARD);
                discountService.remove(wrapper);

                wrapper = new QueryWrapper();
                wrapper.eq("CARD_ID", card.getOid());
                couponSendService.remove(wrapper);
            }
        }
    }

    @PostMapping(value = "/reject")
    @ApiOperation("對單取消單")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult reject(DsgApplyCheck check) {
        //新增對單記錄
        check.setOid(UUIDGenerator.getUUID());
        check.setCheckTime(new Date());
        check.setCheckResult(DsgApplyCheck.CHECK_RESULT_CANCEL);
        SystemAuthorizingUser sysUser = SingletonLoginUtils.getSystemUser();
        check.setChecker(sysUser.getUserId());
        checkService.save(check);

        //申請單變成：取消
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("APP_NO", check.getAppNo());
        DsgApplyBill bill = service.getOne(wrapper);
        if (DsgApplyBill.APP_STATUS_2 == bill.getAppStatus())
            return fail("申請單已是取消狀態");
        bill.setPreAppStatus(bill.getAppStatus());
        bill.setAppStatus(DsgApplyBill.APP_STATUS_2);
        service.updateById(bill);

        //所有車變成：拒絕
        List<DsgApplyCar> carList = carService.list(wrapper);
        for (DsgApplyCar car : carList) {
            car.setPreCarStatus(car.getCarStatus());
            car.setCarStatus(DsgApplyCar.CAR_STATUS_CANCEL);
        }
        carService.updateBatchById(carList);

        return success();
    }

    @PostMapping(value = "/cancel")
    @ApiOperation("AOS取消")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult cancel(@RequestBody DsgApplyBill bill) {
        if (StringUtil.isEmpty(bill.getAppNo()))
            return fail("appNo不能為空");
        if (StringUtil.isEmpty(bill.getRemark()))
            return fail("取消原因不能為空");
        //申請單變成：取消
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("APP_NO", bill.getAppNo());
        DsgApplyBill bill1 = service.getOne(wrapper);
        if (DsgApplyBill.APP_STATUS_2 == bill1.getAppStatus())
            return fail("申請單已是取消狀態");

        bill1.setCancelTime(new Date());
        bill1.setRemark(bill.getRemark());
        bill1.setPreAppStatus(bill1.getAppStatus());
        bill1.setAppStatus(DsgApplyBill.APP_STATUS_2);
        service.updateById(bill1);

        //所有車變成：拒絕
        List<DsgApplyCar> carList = carService.list(wrapper);
        for (DsgApplyCar car : carList) {
            car.setPreCarStatus(car.getCarStatus());
            car.setCarStatus(DsgApplyCar.CAR_STATUS_CANCEL);
        }
        carService.updateBatchById(carList);

        return success();
    }

    @PostMapping(value = "/reburnContinue")
    @ApiOperation("AOS翻生-繼續")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult reburnContinue(@RequestBody DsgApplyBill bill) {
        if (StringUtil.isEmpty(bill.getAppNo()))
            return fail("appNo不能為空");
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("APP_NO", bill.getAppNo());
        bill = service.getOne(wrapper);
        if (DsgApplyBill.APP_STATUS_2 != bill.getAppStatus())
            return fail("取消狀態才能翻生");
        bill.setAppStatus(bill.getPreAppStatus());
        service.updateById(bill);

        List<DsgApplyCar> carList = carService.list(wrapper);
        for (DsgApplyCar car : carList) {
            car.setCarStatus(car.getPreCarStatus());
        }
        carService.updateBatchById(carList);

        return success();
    }

    @PostMapping(value = "/todo")
    @ApiOperation("對單待跟进")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult todo(@RequestBody DsgApplyCheck check) {
        check.setOid(UUIDGenerator.getUUID());
        check.setCheckResult(DsgApplyCheck.CHECK_RESULT_TODO);
        SystemAuthorizingUser sysUser = SingletonLoginUtils.getSystemUser();
        check.setChecker(sysUser.getUserId());
        checkService.save(check);
        return success();
    }

    //在最後對單點擊“完成對單”的時候，才會真的走一次內審，並且將結果存儲。
    //假若真的因為付款資料不通過(應該是人、車、付款資料)，申請單要變成拒絕單，然後對單狀態為完成
    @PostMapping(value = "/done")
    @ApiOperation("對單完成對單")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult checkListDone(String appNo) throws Exception {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("APP_NO", appNo);
        DsgApplyBill bill = service.getOne(wrapper);

        wrapper.eq("APP_NO", appNo);
        List<DsgApplyCard> cardList = cardService.list(wrapper);

        if (bill.getKeepType() == DsgApplyBill.KEEP_TYPE_BOOK) {
            for (DsgApplyCard card : cardList) {
                if (StringUtil.isEmpty(card.getPayId()))
                    throw new Exception("存在還沒有綁定付款資料的車輛");
            }
        }

        if (service.internalAudit(bill)) {
            bill.setAppStatus(DsgApplyBill.APP_STATUS_4);
            DsgApproveCase approveCase = caseService.getCase(WorkflowService3.NODE_CHECK_LIST, appNo);
            if (approveCase == null)
                return fail("對單CASE不存在");
            engine.forward(approveCase);

            //折扣生效
            for (DsgApplyCard card : cardList) {
                LambdaUpdateWrapper<DsgApplyDiscount> updateWrapper = new LambdaUpdateWrapper();
                updateWrapper.eq(DsgApplyDiscount::getCardId, card.getOid());
                updateWrapper.set(DsgApplyDiscount::getDisStatus, DsgApplyDiscount.DIS_STATUS_1);
                discountService.update(new DsgApplyDiscount(), updateWrapper);
            }
            DsgApplyCus cus = cusService.getById(bill.getCusId());
            String cusNo = null;
            if (cus != null) {
                cusNo = cus.getCusNo();
            } else {
                DsgApplyCom  com = comService.getById(bill.getCusId());
                cusNo = com.getComNo();
            }
            LambdaUpdateWrapper<DsgApplyDiscount> updateWrapper = new LambdaUpdateWrapper();
            updateWrapper.eq(DsgApplyDiscount::getCusNo, cusNo);
            updateWrapper.set(DsgApplyDiscount::getDisStatus, DsgApplyDiscount.DIS_STATUS_1);
            discountService.update(new DsgApplyDiscount(), updateWrapper);
        } else {
            bill.setAppStatus(DsgApplyBill.APP_STATUS_2);
        }
        bill.setCheckNo(SnowflakeKeyWorker.nextStrId());
        bill.setIsMatch(DsgApplyBill.IS_MATCH_Y);
        service.updateById(bill);
        statusService.setIsMatch(bill.getAppNo());

        DsgApplyCheck check = new DsgApplyCheck();
        check.setOid(UUIDGenerator.getUUID());
        check.setAppNo(appNo);
        check.setCheckResult(DsgApplyCheck.CHECK_RESULT_DONE);
        SystemAuthorizingUser sysUser = SingletonLoginUtils.getSystemUser();
        check.setChecker(sysUser.getUserId());
        checkService.save(check);

        return success();
    }

    @PostMapping(value = "/transmit")
    @ApiOperation("對單转交跟进")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult transmit(@RequestParam String appNo, @RequestParam String userOid) {
//        engine.transmit(appNo, userOid);//TODO
        return success();
    }

    @PostMapping(value = "/addCar")
    @ApiOperation("對單加車")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult addCar(String oldBillOid, String newBillOid) throws Exception {
        DsgApplyBill newBill;
        if (StringUtil.isEmpty(newBillOid)) {
            newBill = service.getById(oldBillOid);
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("MAIN_NO", newBill.getMainNo());
            if (service.count(wrapper) > 1) {
                throw new Exception("單號" + newBill.getMainNo() + "已生成過新單");
            }
            newBill.setOid(UUIDGenerator.getUUID());
            if (DsgApplyBill.KEEP_TYPE_CASH == newBill.getKeepType()) {
                newBill.setAppType(DsgApplyBill.APP_TYPE_27);
            } else {
                newBill.setAppType(DsgApplyBill.APP_TYPE_19);
            }
            String appNo = DateUtil.format(new Date(), "yyyyMMddHHmmss");
            newBill.setAppNo(appNo);
            newBill.setAppStatus(DsgApplyBill.APP_STATUS_DRAFT);
            service.save(newBill);
            engine.begin(newBill);
        } else {
            newBill = service.getById(newBillOid);
        }

        DsgApplyCar car = new DsgApplyCar();
        car.setOid(UUIDGenerator.getUUID());
        car.setMainNo(newBill.getMainNo());
        car.setAppNo(newBill.getAppNo());
        carService.save(car);

        ChangeCarDto dto = new ChangeCarDto();
        dto.setNewBill(newBill);
        dto.setCar(car);

        return json(MessageConstants.SSO_STATUS_SUCCESS, dto);
    }

    /**
     * 對單时设成用回旧卡，过一元成功后，把新卡的折扣copy给旧卡
     *
     * @param cardOid
     * @param appNo
     * @return
     */
    @PostMapping(value = "/useOldCard")
    @ApiOperation("對單用回旧卡")
    public AjaxResult useOldCard(String cardOid, String appNo) {
        DsgApplyStatus status = getStatus(cardOid, appNo);
        status.setIsUseOld(DsgApplyStatus.IS_USE_OLD_Y);
        statusService.updateById(status);
        return success();
    }

    @PostMapping(value = "/notUseOldCard")
    @ApiOperation("對單取消用回旧卡")
    public AjaxResult notUseOldCard(String cardOid, String appNo) {
        DsgApplyStatus status = getStatus(cardOid, appNo);
        status.setIsUseOld(DsgApplyStatus.IS_USE_OLD_N);
        statusService.updateById(status);
        return success();
    }

    private DsgApplyStatus getStatus(String cardOid, String appNo) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("CARD_ID", cardOid);
        wrapper.eq("APP_NO", appNo);
        DsgApplyStatus status = statusService.getOne(wrapper);
        return status;
    }

    @PostMapping(value = "/cancelCard")
    @ApiOperation("對單时取消勾选卡，取消勾選等同於“取消車”功能")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult cancelCard(String cardOid, String reason) {
        DsgApplyCard card = cardService.getById(cardOid);
        card.setCardStatus(DsgApplyCard.CARD_STATUS_CANCEL);
        cardService.updateById(card);

        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("APP_NO", card.getAppNo());
        wrapper.ne("CARD_STATUS", DsgApplyCard.CARD_STATUS_CANCEL);
        List<DsgApplyCard> cardList = cardService.list(wrapper);

        //车取消，当该车所有的卡都已经取消
        if (CollectionUtil.isEmpty(cardList)) {
            wrapper = new QueryWrapper();
            wrapper.eq("APP_NO", card.getAppNo());
            DsgApplyCar car = carService.getOne(wrapper);
            car.setCarStatus(DsgApplyCar.CAR_STATUS_CANCEL);
            carService.updateById(car);
        }

        DsgApplyCheck check = new DsgApplyCheck();
        check.setCheckResult(DsgApplyCheck.CHECK_RESULT_CANCEL);
        check.setOid(UUIDGenerator.getUUID());
        check.setAppNo(card.getAppNo());
        check.setCardId(cardOid);
        check.setCheckRemarks(reason);
        check.setCheckTime(new Date());
        check.setChecker(getUserId());
        checkService.save(check);

        return success();
    }

    @PostMapping(value = "/selectCard")
    @ApiOperation("對單时重新勾选卡")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult selectCard(String cardOid) {
        DsgApplyCard card = cardService.getById(cardOid);
        card.setCardStatus(DsgApplyCard.CARD_STATUS_APPLY);
        cardService.updateById(card);

        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("APP_NO", card.getAppNo());
        DsgApplyCar car = carService.getOne(wrapper);
        car.setCarStatus(DsgApplyCar.CAR_STATUS_RECORD);
        carService.updateById(car);

        return success();
    }

    @PostMapping(value = "/editInRemarks")
    @ApiOperation("對單时修改内部备注")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult editInRemarks(String billOid, String content) {
        DsgApplyBill bill = new DsgApplyBill();
        bill.setOid(billOid);
        bill.setInRemarks(content);
        service.updateById(bill);
        return success();
    }

    private List<DsgApplyContact> getContactList(String cusOid) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("PID", cusOid);
        return contactService.list(wrapper);
    }

    @PostMapping(value = "/transCard")
    @ApiOperation("轉移油咭 複製數據後前端調用csView接口返回數據")
    @Transactional(rollbackFor = Exception.class)
    @ApiResponses({
            @ApiResponse(response = CsApplyDetailDto.class, code = 1, message = "ok")
    })
    public AjaxResult transCard(@ApiParam(required = true) @RequestParam String carOids,
                                @ApiParam(required = true) @RequestParam String cardOids,
                                String cusNo,
                                @ApiParam(required = true) @RequestParam MultipartFile file) throws Exception {
        if (StringUtil.isEmpty(carOids)) {
            return fail("carOids不能為空");
        }
        if (StringUtil.isEmpty(cardOids)) {
            return fail("cardOids不能為空");
        }
        CsApplyDetailDto detailDto = new CsApplyDetailDto();
        List<String> cardOidList = Arrays.asList(cardOids.split(","));
        List<DsgApplyCard> cardList1 = cardService.listByIds(cardOidList);
        for (DsgApplyCard card : cardList1) {
            if (DsgApplyCard.CARD_STATUS_4 != card.getCardStatus())
                return fail("生效中的油咭才能轉移油咭");
        }
        if (CollectionUtil.isEmpty(cardList1)) {
            return fail("不存在油咭");
        }
        String cusNo1 = cardList1.get(0).getCusNo();
        QueryWrapper wrapper1 = new QueryWrapper();
        wrapper1.eq("CUS_NO", cusNo1);
        DsgApplyCus cus1 = cusService.getOne(wrapper1);
        if (cus1 != null) {
            detailDto.setCusOrCom(Constant.IS_CUS);
        } else {
            detailDto.setCusOrCom(Constant.IS_COM);
        }

        //前咭取消
        cardList1.forEach(e -> e.setCardStatus(DsgApplyCard.CARD_STATUS_CANCEL));
        cardService.updateBatchById(cardList1);

        DsgApplyBill bill = new DsgApplyBill();
        bill.setOid(UUIDGenerator.getUUID());
        final String appNo = DateUtil.format(new Date(), "yyyyMMddHHmmss");
        bill.setAppNo(appNo);
        bill.setKeepType(DsgApplyBill.KEEP_TYPE_BOOK);
        bill.setApplyTime(new Date());
        SystemAuthorizingUser sysUser = SingletonLoginUtils.getSystemUser();
        bill.setSalerNo(sysUser.getUserName());
        bill.setSaleTeam(sysUser.getOrgCode());
        int appType = DsgApplyBill.APP_TYPE_16;
        boolean isOldCus = false;
        String mainNO = null;
        DsgApplyCus cus = null;
        DsgApplyCom com = null;
        String cusId = null;

        if (StringUtil.isNotEmpty(cusNo)) {
            bill.setPayType(Constant.PAY_TYPE_ATP);
            appType = DsgApplyBill.APP_TYPE_15;
            isOldCus = true;
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("CUS_NO", cusNo);
            cus = cusService.getOne(wrapper);
            if (cus != null) {
                mainNO = cus.getMainNo();
                cusId = cus.getOid();
                detailDto.setCus(cus);
                cus.setContactList(getContactList(cus.getOid()));
            } else {
                wrapper = new QueryWrapper();
                wrapper.eq("COM_NO", cusNo);
                com = comService.getOne(wrapper);
                if (com != null) {
                    mainNO = com.getMainNo();
                    cusId = com.getOid();
                    detailDto.setCom(com);
                    com.setContactList(getContactList(com.getOid()));
                } else {
                    throw new Exception("客戶不存在");
                }
            }
        } else {
            mainNO = appNo;
        }

        bill.setMainNo(mainNO);
        bill.setAppType(appType);
        bill.setCusId(cusId);
        service.save(bill);

        detailDto.setDsgApplyBill(bill);

        List<String> carOidList = Arrays.asList(carOids.split(","));
        List<DsgApplyCar> carList = new ArrayList<>();
        detailDto.setCarList(carList);
        for (String carOid : carOidList) {
            DsgApplyCar car = carService.getById(carOid);
            fillCarRelated(car);
            carList.add(car);
            car.setOid(UUIDGenerator.getUUID());
            car.setAppNo(appNo);
            car.setMainNo(mainNO);
            car.setCusNo(cusNo);
            car.setOwnerId(null);
            car.setCarOwner(null);
            car.setCreater(null);
            car.setCreateTime(null);
            car.setUpdater(null);
            car.setUpdateTime(null);
            car.setCarStatus(DsgApplyCar.CAR_STATUS_NOT_RECORD);

            DsgApplyQuestion question = car.getQuestion();
            if (question != null) {
                question.setOid(UUIDGenerator.getUUID());
                question.setCarId(car.getOid());
                question.setCreater(null);
                question.setCreateTime(null);
                question.setUpdater(null);
                question.setUpdateTime(null);
                questionService.save(question);
            }

            List<DsgApplyCard> cardList = car.getCardList();
            if (CollectionUtil.isNotEmpty(cardList)) {
                List<DsgApplyStatus> statusList = new ArrayList<>();
                List<DsgApplyCard> cardList2 = new ArrayList<>();
                for (DsgApplyCard card : cardList) {
                    if (!cardOidList.contains(card.getOid())) {
                        continue;
                    } else {
                        cardList2.add(card);
                    }

                    card.setAppNo(appNo);
                    card.setCarId(car.getOid());
                    card.setOid(UUIDGenerator.getUUID());
                    card.setCreater(null);
                    card.setCreateTime(null);
                    card.setUpdater(null);
                    card.setUpdateTime(null);

                    DsgApplyStatus status = new DsgApplyStatus();
                    status.setOid(UUIDGenerator.getUUID());
                    status.setAppNo(appNo);
                    status.setCardId(card.getOid());
                    status.setAppType(appType);
                    status.setCarNo(car.getCarNo());
                    statusList.add(status);

                    List<DsgApplyDiscount> cardDiscountList = card.getDiscountList();
                    if (CollectionUtil.isNotEmpty(cardDiscountList)) {
                        for (DsgApplyDiscount discount : cardDiscountList) {
                            discount.setOid(UUIDGenerator.getUUID());
//                            discount.setAppNo(appNo);
                            discount.setCardId(card.getOid());
                            discount.setCreater(null);
                            discount.setCreateTime(null);
                            discount.setUpdater(null);
                            discount.setUpdateTime(null);
                        }
                        discountService.saveBatch(cardDiscountList);
                    }

                    DsgCouponSend couponSend = card.getCoupon();
                    if (couponSend != null) {
                        couponSend.setOid(UUIDGenerator.getUUID());
                        couponSend.setCardId(card.getOid());
                        couponSend.setAppNo(appNo);
                        couponSend.setCreater(null);
                        couponSend.setCreateTime(null);
                        couponSend.setUpdater(null);
                        couponSend.setUpdateTime(null);
                        couponSendService.save(couponSend);
                    }
                }
                car.setCardList(cardList2);
                if (CollectionUtil.isNotEmpty(cardList2)) {
                    cardService.saveBatch(cardList2);
                }
                if (CollectionUtil.isNotEmpty(statusList)) {
                    statusService.saveBatch(statusList);
                }
            }
        }
        carService.saveBatch(carList);

        if (isOldCus) {
            List<DsgApplyDiscount> cusDiscountList = detailDto.getCusDiscountList();
            if (CollectionUtil.isNotEmpty(cusDiscountList)) {
                for (DsgApplyDiscount discount : cusDiscountList) {
                    discount.setOid(UUIDGenerator.getUUID());
//                    discount.setAppNo(bill.getAppNo());
                    discount.setCusNo(cusNo);
                }
                discountService.saveBatch(cusDiscountList);
            }

            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("MAIN_NO", mainNO);
            List<DsgApplyPay> payList = payService.list(wrapper);
            detailDto.setPayList(payList);
        }

        String fileName = file.getOriginalFilename();
        String fileType = fileName.split("\\.")[1];
        File f = FileUtil.multipartToFile(file);
        DsgSysFile sysFile = new DsgSysFile();
        sysFile.setAppNo(appNo);
        sysFile.setEnclType(DsgSysFile.ENCL_TYPE_10);
        fileService.saveFile(sysFile, f, bill.getOid(), fileType);

//        engine.begin(bill);

        return success(detailDto);
    }

    @PostMapping(value = "/batchModifyDiscount")
    @ApiOperation("批量修改折扣")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult batchModifyDiscount(@ApiParam(required = true) @RequestParam String cardNos,
                                          @ApiParam(required = true) @RequestParam String discountType,
                                          @ApiParam(required = true) @RequestParam Integer cheepAmount,
                                          @ApiParam(required = true) @RequestParam Integer costlyAmount) {
        List<String> cardNoList = Arrays.asList(cardNos.split(","));
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.in("CARD_NO", cardNoList);
        List<DsgApplyCard> cardList = cardService.list(wrapper);
        List<String> cardOidList = cardList.stream().map(DsgApplyCard::getOid).collect(Collectors.toList());

        LambdaUpdateWrapper<DsgApplyDiscount> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.in(DsgApplyDiscount::getCardId, cardOidList);
        updateWrapper.eq(DsgApplyDiscount::getDiscountType, discountType);
        updateWrapper.eq(DsgApplyDiscount::getEntCode, getEntCode());
        DsgApplyDiscount discount = new DsgApplyDiscount();
        discount.setCheepAmount(cheepAmount);
        discount.setCostlyAmount(costlyAmount);
        discountService.update(discount, updateWrapper);

        return success();
    }

    @PostMapping(value = "/csAddCar")
    @ApiOperation("CS加車")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult csAddCar(String cusNo) throws Exception {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("CUS_NO", cusNo);
        wrapper.eq("ENT_CODE", getEntCode());
        DsgApplyCus cus = cusService.getOne(wrapper);
        String mainNo = null;
        if (cus != null) {
            mainNo = cus.getMainNo();
        } else {
            wrapper = new QueryWrapper();
            wrapper.eq("COM_NO", cusNo);
            wrapper.eq("ENT_CODE", getEntCode());
            DsgApplyCom com = comService.getOne(wrapper);
            if (com != null) {
                mainNo = com.getMainNo();
            }
        }

        if (StringUtil.isEmpty(mainNo)) {
            throw new Exception("通過客戶編號找不到主單號");
        }

        wrapper = new QueryWrapper();
        wrapper.eq("MAIN_NO", mainNo);
        wrapper.eq("APP_NO", mainNo);
        DsgApplyBill bill = service.getOne(wrapper);
        if (DsgApplyBill.KEEP_TYPE_CASH == bill.getKeepType()) {
            bill.setAppType(DsgApplyBill.APP_TYPE_24);
        } else {
            bill.setAppType(DsgApplyBill.APP_TYPE_7);
        }
        bill.setOid(UUIDGenerator.getUUID());
        bill.setCreateTime(null);
        bill.setCreater(null);
        bill.setUpdater(null);
        bill.setUpdateTime(null);
        bill.setApplyTime(new Date());
        String appNo = DateUtil.format(new Date(), "yyyyMMddHHmmss");
        bill.setAppNo(appNo);
        bill.setAppStatus(DsgApplyBill.APP_STATUS_DRAFT);
        bill.setPayId(null);
        bill.setPayType(null);
        service.save(bill);
        return json(MessageConstants.SSO_STATUS_SUCCESS, bill.getOid());
    }

    @GetMapping(value = "/checkBeforeChangeCar")
    @ApiOperation("CS轉車牌、轉油種前檢查")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult checkChangeCar(String oldCarOid, int appType) throws Exception {
        DsgApplyCar car = carService.getById(oldCarOid);
        if (DsgApplyCar.CAR_STATUS_NOT_RECORD == car.getCarStatus())
            throw new Exception("車輛信息未錄入，不能轉車牌、轉油種");

        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("CAR_OID", oldCarOid);
        DsgApplyBill bill = service.getOne(wrapper);
        if (bill != null) {
            String msg = "已做轉車牌";
            if (bill.getAppType() != appType) {
                if (DsgApplyBill.APP_TYPE_5 == bill.getAppType()) {
                    msg = "已做轉油種";
                }
                return fail(msg);
            } else {
                return success(bill.getOid());
            }
        }

        return success();
    }

    @PostMapping(value = "/csChangeOilType")
    @ApiOperation("CS轉油種")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult csChangeOilType(String oldCarOid) throws Exception {
        DsgApplyCar car = carService.getById(oldCarOid);

        if (car.getCarStatus().equals(DsgApplyCar.CAR_STATUS_CANCEL)) {
            return setErrorJson("該車已取消");
        }

        //點轉車牌，轉油種之後，這台車的記錄要變成取消，並標記為CS對單轉車牌/CS對單轉油種 取消
        car.setCarStatus(DsgApplyCar.CAR_STATUS_CANCEL);
        carService.updateById(car);

        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("CAR_ID", oldCarOid);
        List<DsgApplyCard> cardList = cardService.list(wrapper);
        if (CollectionUtil.isNotEmpty(cardList)) {
            for (DsgApplyCard card : cardList) {
                card.setCardStatus(DsgApplyCard.CARD_STATUS_CANCEL);
                card.setRemark("轉油種取消咭");
            }
            cardService.updateBatchById(cardList);
        }

        wrapper = new QueryWrapper();
        wrapper.eq("MAIN_NO", car.getMainNo());
        wrapper.eq("APP_NO", car.getMainNo());
        DsgApplyBill newBill = service.getOne(wrapper);
        newBill.setCarOid(oldCarOid);
        newBill.setOid(UUIDGenerator.getUUID());
        newBill.setMainNo(car.getMainNo());
        String appNo = DateUtil.format(new Date(), "yyyyMMddHHmmss");
        newBill.setAppNo(appNo);
        newBill.setAppType(DsgApplyBill.APP_TYPE_5);
        newBill.setAppStatus(DsgApplyBill.APP_STATUS_DRAFT);
        newBill.setApplyTime(new Date());
        newBill.setCreater(null);
        newBill.setCreateTime(null);
        newBill.setUpdateTime(null);
        newBill.setUpdater(null);
        service.save(newBill);

        //更新原車的狀態表
        wrapper = new QueryWrapper();
        wrapper.eq("CAR_NO", car.getCarNo());
        wrapper.eq("APP_NO", car.getAppNo());
        List<DsgApplyStatus> applyStatusList = statusService.list(wrapper);
        for (DsgApplyStatus applyStatus : applyStatusList) {
            applyStatus.setAppType(newBill.getAppType());
            applyStatus.setAppStatus(DsgApplyStatus.APP_STATUS_CANCEL);
        }
        statusService.updateBatchById(applyStatusList);

        if (car.getCarOilType().equals(DsgApplyCar.CAR_OIL_TYPE_DIESEL)) {
            car.setCarOilType(DsgApplyCar.CAR_OIL_TYPE_GAS);
        } else {
            car.setCarOilType(DsgApplyCar.CAR_OIL_TYPE_DIESEL);
        }

        car.setOid(UUIDGenerator.getUUID());
        car.setAppNo(appNo);
        car.setCarStatus(DsgApplyCar.CAR_STATUS_RECORD);
        car.setCreater(null);
        car.setCreateTime(null);
        car.setUpdateTime(null);
        car.setUpdater(null);
        carService.save(car);

        //车内审
//        carService.audit(newBill, car);
        engine.begin(newBill);

        return json(MessageConstants.SSO_STATUS_SUCCESS, newBill.getOid());
    }

    @PostMapping(value = "/csChangeCarNo")
    @ApiOperation("CS轉車牌")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult csChangeCarNo(String oldCarOid) throws Exception {
        DsgApplyCar car = carService.getById(oldCarOid);

        if (car.getCarStatus().equals(DsgApplyCar.CAR_STATUS_CANCEL)) {
            return setErrorJson("該車已取消");
        }

        //點轉車牌，轉油種之後，這台車的記錄要變成取消，並標記為CS對單轉車牌/CS對單轉油種 取消
        car.setCarStatus(DsgApplyCar.CAR_STATUS_CANCEL);
        carService.updateById(car);

        fillCarRelated(car);

        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("MAIN_NO", car.getMainNo());
        wrapper.eq("APP_NO", car.getMainNo());
        DsgApplyBill newBill = service.getOne(wrapper);
        newBill.setCarOid(oldCarOid);
        newBill.setOid(UUIDGenerator.getUUID());
        newBill.setMainNo(car.getMainNo());
        String appNo = DateUtil.format(new Date(), "yyyyMMddHHmmss");
        newBill.setAppNo(appNo);
        if (DsgApplyBill.KEEP_TYPE_CASH == newBill.getKeepType()) {
            newBill.setAppType(DsgApplyBill.APP_TYPE_25);
        } else {
            newBill.setAppType(DsgApplyBill.APP_TYPE_4);
        }
        newBill.setAppStatus(DsgApplyBill.APP_STATUS_DRAFT);
        newBill.setApplyTime(new Date());
        newBill.setCreater(null);
        newBill.setCreateTime(null);
        newBill.setUpdateTime(null);
        newBill.setUpdater(null);
        service.save(newBill);

        //更新原車的狀態表
        wrapper = new QueryWrapper();
        wrapper.eq("CAR_NO", car.getCarNo());
        wrapper.eq("APP_NO", car.getAppNo());
        List<DsgApplyStatus> applyStatusList = statusService.list(wrapper);
        for (DsgApplyStatus applyStatus : applyStatusList) {
            applyStatus.setAppType(newBill.getAppType());
            applyStatus.setAppStatus(DsgApplyStatus.APP_STATUS_CANCEL);
        }
        statusService.updateBatchById(applyStatusList);

        car.setOid(UUIDGenerator.getUUID());
        car.setAppNo(appNo);
        car.setCarNo(null);
        car.setCarStatus(DsgApplyCar.CAR_STATUS_NOT_RECORD);
        car.setCreater(null);
        car.setCreateTime(null);
        car.setUpdateTime(null);
        car.setUpdater(null);
        carService.save(car);

        for (DsgApplyCard card : car.getCardList()) {
            card.setCardStatus(DsgApplyCard.CARD_STATUS_CANCEL);
        }
        cardService.updateBatchById(car.getCardList());

        copyCarRelated(car, newBill.getAppType());

        //车内审
//        carService.audit(newBill, car);
        engine.begin(newBill);

        return json(MessageConstants.SSO_STATUS_SUCCESS, newBill.getOid());
    }

    @GetMapping(value = "/selectSupApproveList")
    @ApiOperation("上級批核列表")
    @ApiResponses({
            @ApiResponse(response = SupApproveDto.class, code = 1, message = "ok")
    })
    public AjaxResult selectSupApproveList(Integer appType, String approveStatus) {
        Page page = getPage();
        page = service.selectSupApproveList(page, appType, approveStatus, getEntCode());
        AjaxResult ajaxResult = json(MessageConstants.SSO_STATUS_SUCCESS, page.getRecords(), (int) page.getTotal());
        return ajaxResult;
    }

    @PutMapping(value = "/approve")
    @ApiOperation("上級批核")
    @ApiResponses({
            @ApiResponse(response = SupApproveDto.class, code = 1, message = "ok")
    })
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult approve(@RequestParam String appNo, @RequestParam Integer approveStatus) throws Exception {
        LambdaUpdateWrapper<DsgApplyBill> wrapper = new LambdaUpdateWrapper();
        wrapper.eq(DsgApplyBill::getAppNo, appNo);
        wrapper.set(DsgApplyBill::getApproveStatus, approveStatus);
        wrapper.set(DsgApplyBill::getApprover, getUserId());
        service.update(new DsgApplyBill(), wrapper);
        DsgApproveCase approveCase = caseService.getCase(WorkflowService3.NODE_SUP_APPROVE, appNo);
        engine.forward(approveCase);
        return success();
    }

    /**
     * 取消過期補領
     *
     * @return
     */
    @PutMapping(value = "/cancelExpiredReplacement")
    @ApiOperation("取消過期補領")
    public AjaxResult cancelExpiredReplacement(@ApiParam(value = "id以，号分隔", name = "idList", required = true) @RequestParam String idList) {
        boolean flag = service.cancelExpiredReplacement(Arrays.asList(idList.split(",")));
        if (flag) {
            return result(MessageConstants.SSO_STATUS_SUCCESS);
        } else {
            return result(MessageConstants.SSO_STATUS_FAIL);
        }
    }
}
